﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmlStudio.DataLayer;

namespace XmlStudio.DataLayer {
    /// <summary>
    /// Helper class for xsd structure.
    /// </summary>
    public static class XsdStructure {
        /// <summary>
        /// Returns collection of possible content for the specified xsd element type.
        /// </summary>
        /// <param name="element">Xsd element type.</param>
        /// <param name="parent">Type of parent element.</param>
        /// <returns>Collection of <see cref="XsdStructureItem"/> instances.</returns>
        public static IEnumerable<XsdStructureItem> GetContent(XsdElement element, XsdElement? parent = null) {
            switch(element) {
                case XsdElement.All:
                    return new List<XsdStructureItem>{ 
                        new XsdStructureItem{ElementType = XsdElement.Annotation, Multiplicity= Multiplicity.ZeroOrOne},
                        new XsdStructureItem{ElementType=XsdElement.Element, Multiplicity = Multiplicity.ZeroOrMore}
                    };
                case XsdElement.Annotation: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.AppInfo, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Documentation, Multiplicity = Multiplicity.One });
                        group.Operator = GroupOperator.Or;
                        group.Multiplicity = Multiplicity.ZeroOrMore;

                        return new List<XsdStructureItem> { group };
                    }
                case XsdElement.Any:
                    return new List<XsdStructureItem> { 
                        new XsdStructureItem { ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne } 
                    };
                case XsdElement.AnyAttribute:
                    return new List<XsdStructureItem>{
                        new XsdStructureItem{ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.AppInfo:
                    return new List<XsdStructureItem>{
                        new XsdStructureItem{ElementType = XsdElement.AnyWellFormedXml, Multiplicity = Multiplicity.ZeroOrMore}
                    };
                case XsdElement.Attribute:
                    return new List<XsdStructureItem> {
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                        new XsdStructureItem{ ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.AttributeGroup: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                        group.Operator = GroupOperator.Or;
                        group.Multiplicity = Multiplicity.ZeroOrMore;
                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group,
                            new XsdStructureItem{ElementType = XsdElement.AnyAttribute, Multiplicity = Multiplicity.ZeroOrOne}
                        };
                    }
                case XsdElement.Choice: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Element, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Any, Multiplicity = Multiplicity.One });
                        group.Multiplicity = Multiplicity.ZeroOrMore;
                        group.Operator = GroupOperator.Or;
                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
                case XsdElement.ComplexContent: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Restriction, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Extension, Multiplicity = Multiplicity.One });
                        group.Operator = GroupOperator.Or;
                        group.Multiplicity = Multiplicity.One;
                        return new List<XsdStructureItem>{
                        new XsdStructureItem { ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                        group
                        };
                    }
                case XsdElement.ComplexType: {
                        var group01 = new XsdStructureGroup();
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.All, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                        group01.Operator = GroupOperator.Or;
                        group01.Multiplicity = Multiplicity.ZeroOrOne;

                        var group02 = new XsdStructureGroup();
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                        group02.Multiplicity = Multiplicity.ZeroOrMore;
                        group02.Operator = GroupOperator.Or;

                        var group03 = new XsdStructureGroup();
                        group03.Items.Add(group02);
                        group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.AnyAttribute, Multiplicity = Multiplicity.ZeroOrOne });
                        group03.Multiplicity = Multiplicity.One;
                        group03.Operator = GroupOperator.And;

                        var group04 = new XsdStructureGroup();
                        group04.Items.Add(group01);
                        group04.Items.Add(group03);
                        group04.Multiplicity = Multiplicity.One;
                        group04.Operator = GroupOperator.And;

                        var group05 = new XsdStructureGroup();
                        group05.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleContent, Multiplicity = Multiplicity.One });
                        group05.Items.Add(new XsdStructureItem { ElementType = XsdElement.ComplexContent, Multiplicity = Multiplicity.One });
                        group05.Items.Add(group04);

                        return new List<XsdStructureItem>{
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group05
                        };
                    }
                case XsdElement.Documentation: {
                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.AnyWellFormedXml, Multiplicity = Multiplicity.ZeroOrMore}
                        };
                    }
                case XsdElement.Element: {
                        var group01 = new XsdStructureGroup();
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.ComplexType, Multiplicity = Multiplicity.One });
                        group01.Multiplicity = Multiplicity.ZeroOrOne;
                        group01.Operator = GroupOperator.Or;

                        var group02 = new XsdStructureGroup();
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Unique, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Key, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.KeyRef, Multiplicity = Multiplicity.One });
                        group02.Multiplicity = Multiplicity.ZeroOrMore;
                        group02.Operator = GroupOperator.Or;

                        var group03 = new XsdStructureGroup();
                        group03.Items.Add(group01);
                        group03.Items.Add(group02);
                        group03.Multiplicity = Multiplicity.One;
                        group03.Operator = GroupOperator.And;

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group03
                        };
                    }
                case XsdElement.Extension: {
                        var group01 = new XsdStructureGroup();
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.All, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                        group01.Multiplicity = Multiplicity.ZeroOrOne;
                        group01.Operator = GroupOperator.Or;

                        var group02 = new XsdStructureGroup();
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                        group02.Multiplicity = Multiplicity.ZeroOrMore;
                        group02.Operator = GroupOperator.Or;

                        var group03 = new XsdStructureGroup();
                        group03.Items.Add(group01);
                        group03.Items.Add(group02);
                        group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.AnyAttribute, Multiplicity = Multiplicity.ZeroOrOne });

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group03
                        };
                    }
                case XsdElement.Field:
                    return new List<XsdStructureItem> {
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.Group: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.All, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                        group.Multiplicity = Multiplicity.ZeroOrOne;
                        group.Operator = GroupOperator.Or;

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
                case XsdElement.Import: {
                        return new List<XsdStructureItem>{
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                    }
                case XsdElement.Include:
                    return new List<XsdStructureItem>{
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.Key: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Selector, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Field, Multiplicity = Multiplicity.OneOrMore });
                        group.Multiplicity = Multiplicity.One;
                        group.Operator = GroupOperator.And;

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne },
                            group
                        };
                    }
                case XsdElement.KeyRef: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Selector, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Field, Multiplicity = Multiplicity.OneOrMore });
                        group.Multiplicity = Multiplicity.One;
                        group.Operator = GroupOperator.And;

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne },
                            group
                        };
                    }
                case XsdElement.List:
                    return new List<XsdStructureItem> {
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                        new XsdStructureItem{ ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.Notation: {
                        return new List<XsdStructureItem>{
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                    }
                case XsdElement.Redefine: {
                        var group01 = new XsdStructureGroup();
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.ComplexType, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                        group01.Multiplicity = Multiplicity.One;
                        group01.Operator = GroupOperator.Or;

                        var group02 = new XsdStructureGroup();
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.One });
                        group02.Items.Add(group01);
                        group02.Multiplicity = Multiplicity.ZeroOrMore;
                        group02.Operator = GroupOperator.Or;

                        return new List<XsdStructureItem>{
                            group02
                        };
                    }
                case XsdElement.Restriction: {
                        if(!parent.HasValue) {
                            throw new ArgumentNullException("parent");
                        }

                        switch(parent.Value) {
                            case XsdElement.SimpleType: {
                                    // Content for simpleType:
                                    // (annotation?,(simpleType?,(minExclusive|minInclusive|maxExclusive|maxInclusive|totalDigits|fractionDigits|
                                    // length|minLength|maxLength|enumeration|whiteSpace|pattern)*))
                                    var group01 = new XsdStructureGroup();
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinExclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinInclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MaxExclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinInclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.TotalDigits, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.FractionDigits, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Length, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinLength, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MaxLength, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Enumeration, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.WhiteSpace, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Pattern, Multiplicity = Multiplicity.One });
                                    group01.Multiplicity = Multiplicity.ZeroOrMore;
                                    group01.Operator = GroupOperator.Or;

                                    var group02 = new XsdStructureGroup();
                                    group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.ZeroOrOne });
                                    group02.Items.Add(group01);
                                    group02.Multiplicity = Multiplicity.One;
                                    group02.Operator = GroupOperator.And;

                                    return new List<XsdStructureItem>{
                                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                                        group02
                                    };
                                }
                            case XsdElement.SimpleContent: {
                                    // Content for simpleContent:
                                    // (annotation?,(simpleType?,(minExclusive|minInclusive|maxExclusive|maxInclusive|totalDigits|fractionDigits|
                                    // length|minLength|maxLength|enumeration|whiteSpace|pattern)*)?,((attribute|attributeGroup)*,anyAttribute?))
                                    var group01 = new XsdStructureGroup();
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinExclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinInclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MaxExclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinInclusive, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.TotalDigits, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.FractionDigits, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Length, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MinLength, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.MaxLength, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Enumeration, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.WhiteSpace, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Pattern, Multiplicity = Multiplicity.One });
                                    group01.Multiplicity = Multiplicity.ZeroOrMore;
                                    group01.Operator = GroupOperator.Or;

                                    var group02 = new XsdStructureGroup();
                                    group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.ZeroOrOne });
                                    group02.Items.Add(group01);
                                    group02.Multiplicity = Multiplicity.ZeroOrOne;
                                    group02.Operator = GroupOperator.And;

                                    var group03 = new XsdStructureGroup();
                                    group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                                    group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                                    group03.Multiplicity = Multiplicity.ZeroOrMore;
                                    group03.Operator = GroupOperator.Or;

                                    var group04 = new XsdStructureGroup();
                                    group04.Items.Add(group03);
                                    group04.Items.Add(new XsdStructureItem { ElementType = XsdElement.AnyAttribute, Multiplicity = Multiplicity.ZeroOrOne });

                                    return new List<XsdStructureItem>{
                                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                                        group02,
                                        group04
                                    };
                                }
                            case XsdElement.ComplexContent: {
                                    // Content for complexContent:
                                    // (annotation?,(group|all|choice|sequence)?,((attribute|attributeGroup)*,anyAttribute?))
                                    var group01 = new XsdStructureGroup();
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.All, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                                    group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                                    group01.Multiplicity = Multiplicity.ZeroOrOne;
                                    group01.Operator = GroupOperator.Or;

                                    var group02 = new XsdStructureGroup();
                                    group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                                    group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                                    group02.Multiplicity = Multiplicity.ZeroOrMore;
                                    group02.Operator = GroupOperator.Or;

                                    return new List<XsdStructureItem>{
                                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                                        group01,
                                        group02,
                                        new XsdStructureItem{ ElementType = XsdElement.AnyAttribute, Multiplicity = Multiplicity.ZeroOrOne}
                                    };
                                }
                        }
                        break;
                    }
                case XsdElement.Selector:
                    return new List<XsdStructureItem>{
                        new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne}
                    };
                case XsdElement.Sequence: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Element, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Choice, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Sequence, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Any, Multiplicity = Multiplicity.One });
                        group.Multiplicity = Multiplicity.ZeroOrMore;
                        group.Operator = GroupOperator.Or;

                        return new List<XsdStructureItem>{
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
                case XsdElement.Schema: {
                        var group01 = new XsdStructureGroup();
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Include, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Import, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Redefine, Multiplicity = Multiplicity.One });
                        group01.Items.Add(new XsdStructureItem { ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.One });
                        group01.Multiplicity = Multiplicity.ZeroOrMore;
                        group01.Operator = GroupOperator.Or;

                        var group02 = new XsdStructureGroup();
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.ComplexType, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.Group, Multiplicity = Multiplicity.One });
                        group02.Items.Add(new XsdStructureItem { ElementType = XsdElement.AttributeGroup, Multiplicity = Multiplicity.One });
                        group02.Multiplicity = Multiplicity.One;
                        group02.Operator = GroupOperator.Or;

                        var group03 = new XsdStructureGroup();
                        group03.Items.Add(group02);
                        group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.Element, Multiplicity = Multiplicity.One });
                        group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.Attribute, Multiplicity = Multiplicity.One });
                        group03.Items.Add(new XsdStructureItem { ElementType = XsdElement.Notation, Multiplicity = Multiplicity.One });
                        group03.Multiplicity = Multiplicity.One;
                        group03.Operator = GroupOperator.Or;

                        var group04 = new XsdStructureGroup();
                        group04.Items.Add(group03);
                        group04.Items.Add(new XsdStructureItem { ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrMore });
                        group04.Multiplicity = Multiplicity.ZeroOrMore;
                        group04.Operator = GroupOperator.And;

                        return new List<XsdStructureItem> {
                            group01,
                            group04
                        };
                    }
                case XsdElement.SimpleContent: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Restriction, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Extension, Multiplicity = Multiplicity.One });

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
                case XsdElement.SimpleType: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Restriction, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.List, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Union, Multiplicity = Multiplicity.One });
                        group.Multiplicity = Multiplicity.One;
                        group.Operator = GroupOperator.Or;

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
                case XsdElement.Union: {
                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            new XsdStructureItem{ ElementType = XsdElement.SimpleType, Multiplicity = Multiplicity.ZeroOrMore}
                        };
                    }
                case XsdElement.Unique: {
                        var group = new XsdStructureGroup();
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Selector, Multiplicity = Multiplicity.One });
                        group.Items.Add(new XsdStructureItem { ElementType = XsdElement.Field, Multiplicity = Multiplicity.OneOrMore });

                        return new List<XsdStructureItem> {
                            new XsdStructureItem{ ElementType = XsdElement.Annotation, Multiplicity = Multiplicity.ZeroOrOne},
                            group
                        };
                    }
            }

            return null;
        }
    }
}
